/**
 *******************************************************************************
 * @FileName  : pan108x_gpio.c
 * @Author    : GaoQiu
 * @CreateDate: 2023-08-01
 * @Copyright : Copyright(C) Panchip
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * Panchip and is available under the terms of Commercial License Agreement
 * between Panchip and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */
#include "pan10x_gpio.h"

void GPIO_DefInit(void)
{
	CLK_AHBPeriphClockCmd(CLK_AHBPeriph_GPIO, ENABLE);

	//GPIO->DBCTL &= ~BIT31;

	//P0
	P0->MODE = 0x00000000;
#ifdef IP_108
	P0->DINOFF = 0x00FF0000;
#elif defined(IP_107)
	P0->DINOFF = 0x00FC0003; //pan107 P00/P01 -> SWD
#endif

	//P1
	P1->MODE = 0x00000000;
	P1->DINOFF = 0x00FF0000;

	//P2
	P2->MODE = 0x00000000;
	P2->DINOFF = 0x00FF0000;

	//P3
	P3->MODE = 0x00000000;
	P3->DINOFF = 0x00FF0000;

#ifdef IP_108
	//P4
	P4->MODE = 0x00000000;
	P4->DINOFF = 0x003F00C0; //pan108 P46/P47 -> SWD

	//P5
	P5->MODE = 0x00000000;
	P5->DINOFF = 0x00FF0000;
#endif

	CLK_AHBPeriphClockCmd(CLK_AHBPeriph_GPIO, DISABLE);
}

void GPIO_SetAFunc(uint16_t GPIO_Pxx, uint32_t GPIO_AF)
{
	if(GPIO_Pxx == GPIO_Pin_None)
		return;

	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	uint8_t pos = (31 - __CLZ(bit));

	__IO uint32_t *pGPIO_AF = (__IO uint32_t *)(GPIO_AF_BASE_ADDR + (grpId << 2));

	uint32_t v = *pGPIO_AF;
	v &= ~(0x00010101 << pos);
	v |= (GPIO_AF<<pos);
	*pGPIO_AF = v;
}

void GPIO_SetITEnable(uint16_t GPIO_Pxx, uint32_t GPIO_IT_Mode)
{
	if(GPIO_Pxx == GPIO_Pin_None)
		return;

	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	uint8_t pos = (31 - __CLZ(bit));
	GPIO_Type_t *pGPIOx = (GPIO_Type_t *)(GPIO_BASE_ADDR + (grpId << 6));

	uint32_t intType = pGPIOx->INT_TYPE;
	uint32_t intEn = pGPIOx->INT_EN;

	intType &= ~bit;
	intEn   &= ~((bit<<16)|(bit<<0));

	intType |= ((GPIO_IT_Mode >> 24)<<pos);
	//intEn   |= ((GPIO_IT_Mode & 0x00FF00FF)<<pos);
	intEn   |= ((GPIO_IT_Mode & 0x00010001)<<pos);

	pGPIOx->INT_TYPE = intType;
	pGPIOx->INT_EN   = intEn;
}

void GPIO_SetITDisable(uint16_t GPIO_Pxx)
{
	if(GPIO_Pxx == GPIO_Pin_None)
		return;

	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	GPIO_Type_t *pGPIOx = (GPIO_Type_t *)(GPIO_BASE_ADDR + (grpId << 6));

	pGPIOx->INT_TYPE &= ~bit;
	pGPIOx->INT_EN   &= ~((bit<<16)|(bit<<0));
}

uint8_t GPIO_GetITState(uint16_t GPIO_Pxx)
{
	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	GPIO_Type_t *pGPIOx = (GPIO_Type_t *)(GPIO_BASE_ADDR + (grpId << 6));

	return (pGPIOx->INT_SRC & bit) ? true:false;
}

void GPIO_ClearITState(uint16_t GPIO_Pxx)
{
	if(GPIO_Pxx == GPIO_Pin_None)
		return;

	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	GPIO_Type_t *pGPIOx = (GPIO_Type_t *)(GPIO_BASE_ADDR + (grpId << 6));

	pGPIOx->INT_SRC = bit;//write 1 clear 0
}

void GPIO_SetDebounceEnable(uint16_t GPIO_Pxx, uint8_t en)
{
	if(GPIO_Pxx == GPIO_Pin_None)
		return;

	uint8_t grpId = (GPIO_Pxx >> 8) & 0x0f;
	uint8_t bit = GPIO_Pxx & 0xff;
	GPIO_Type_t *pGPIOx = (GPIO_Type_t *)(GPIO_BASE_ADDR + (grpId << 6));

	if(en){
		pGPIOx->DB_EN |= bit;
	}
	else{
		pGPIOx->DB_EN &= ~bit;
	}
}

/* 107: Only use standby mode */
void GPIO_SetWakeupLevel(uint8_t high)
{
#ifdef IP_108

#elif defined(IP_107)
	if(high){
		ANA->LP_FL_CTRL_3V |= ANAC_FL_EXT_WAKEUP_SEL_Msk_3v;
	}else{
		ANA->LP_FL_CTRL_3V &= ~ANAC_FL_EXT_WAKEUP_SEL_Msk_3v;
	}
#endif
}

#if CFG_OS_EN
__define_initcall(GPIO_DefInit, 0)
#endif
